import WebSocket from 'ws';
import { SocksProxyAgent } from 'socks-proxy-agent';
import axios from 'axios';
import crypto from 'crypto';
import _ from 'lodash';
import utils from '../../utils/index.js';
import { queue } from 'async';
import fs from 'fs';

// API 配置
let API_KEY = '';
let API_SECRET = '';

// WebSocket 和 API 端点配置
let accountSocketUrl = 'wss://fstream.binance.com';
let accountApiUrl = 'https://fapi.binance.com';
let webSocketUrl = 'wss://fstream.binance.com';

let arginAccount = 0;
let isolatedAccount = 0;

// 动态导入配置文件，修复import语法错误
const configName = utils.arguments('config');
if (!configName) {
  throw new Error('请通过 --config=xxx 指定配置文件名');
}
// 策略参数
const config = await import(`./configs/${configName}.js`).then(m => m.default || m);
config.name  = configName;
const MAX_POSITIONS = config.maxPositions || 3;

// 读取交易记录
let trades = {
    times : 0,
    dates: {},
    symbols: {},
    history: [],
};
try {
    trades = JSON.parse(fs.readFileSync(`/tmp/trades.${configName}.json`, 'utf-8') || '[]');
} catch (err) {
}
const addTrade = (symbol, orderId, rp, data = []) => {
    const date = new Date().toISOString().split('T')[0];
    let trade = trades.history.find(t => t.symbol === symbol && (t.orderId === orderId || t.rp === 0));
    if (trade) {
        trade.orderId = orderId;
        trade.rp += rp;
    } else {
        trade = {symbol, orderId, rp, data, date, timestamp: new Date().getTime() };
         // 累加落单次数
        trades.times++;
        trades.history = [trade, ...trades.history]
    }
    let symbolTrades = _.get(trades, `symbols.${symbol}`, []);
    // 记录最近 12 小时的交易记录并且不含当前交易
    symbolTrades = symbolTrades
            .filter(t => t.timestamp > new Date().getTime() - 12 * 60 * 60 * 1000 && t.orderId !== orderId);
    symbolTrades = [trade, ...symbolTrades];
    _.set(trades, `symbols.${symbol}`, symbolTrades);
    // 记录每天的盈亏
    trades.dates[date] = (trades.dates[date] || 0) + rp;
    const length = config.tradeSize || 15;
    // 保留最近的交易记录
    if (trades.history.length > length) {
        trades.history = trades.history.slice(0, length);
    }
    fs.writeFileSync(`/tmp/trades.${configName}.json`, JSON.stringify(trades))
}

// 创建 SOCKS 代理代理
const agent = utils.Config.proxy ? new SocksProxyAgent(utils.Config.proxy) : null;

// 创建 axios 实例，统一配置代理和超时
const axiosInstance = axios.create({
    httpAgent: agent,
    httpsAgent: agent,
    timeout: 10000,
});

// 获取所有交易对信息
const funGetSymbols = async () => {
    const { data } = await axiosInstance.get(`${accountApiUrl}/fapi/v1/premiumIndex`);
    return data.filter((item) => item.symbol.indexOf('_') === -1);
};

const funcGetSymbolDailPrice = async (symbol) => {
    const timestamps = utils.getTodayZeroTimestamps(['UTC', 'Asia/Shanghai']);
    const file = `./dates/daiy_price.${[symbol, ...timestamps].join('_')}.json`;
    const lockFile = `${file}.lock`;
    // 检查缓存文件是否存在
    if (fs.existsSync(file)) {
        try {
            return JSON.parse(fs.readFileSync(file, 'utf8'));
        } catch {
            fs.unlinkSync(file); // 删除损坏的缓存文件
        }
    }

    // 尝试获取锁
    let lockAcquired = false;
    try {
        fs.writeFileSync(lockFile, process.pid.toString(), { flag: 'wx' });
        lockAcquired = true;
    } catch {
        // 锁被占用，直接返回 null
        return null;
    }

    try {
        // 清理历史缓存文件
        const pattern = `daiy_price.${symbol}_`;
        fs.readdirSync('./dates')
            .filter(f => f.startsWith(pattern))
            .forEach(f => fs.unlinkSync(`./dates/${f}`));

        // 获取数据
        const { data } = await axiosInstance.get(`${accountApiUrl}/fapi/v1/klines`, {
            params: { symbol, interval: '1h', limit: 100 }
        });

        // 格式化K线数据
        const formattedData = data.map(kline => ({
            timestamp: kline[0],
            openTime: utils.formatBeijingDateTime(new Date(kline[0])),
            open: parseFloat(kline[1]),
            high: parseFloat(kline[2]),
            low: parseFloat(kline[3]),
            close: parseFloat(kline[4]),
            volume: parseFloat(kline[5]),
            closeTime: utils.formatBeijingDateTime(new Date(kline[6])),
            quoteVolume: parseFloat(kline[7]),
            trades: parseInt(kline[8]),
            takerBuyVolume: parseFloat(kline[9]),
            takerBuyQuoteVolume: parseFloat(kline[10])
        })).filter(item => item.timestamp == timestamps[0] || item.timestamp == timestamps[1]);
        // 写入缓存
        fs.writeFileSync(file, JSON.stringify(formattedData));
        return formattedData;
    } finally {
        // 释放锁
        if (lockAcquired) {
            try { fs.unlinkSync(lockFile); } catch {}
        }
    }
}

// 缓存交易所信息
let ExchangeInfo = null;

/**
 * 获取交易所信息
 * @param {string} symbol - 交易对符号（可选）
 * @returns {Object} 交易所信息
 */
const funGetExchangeInfo = async (symbol) => {
    if (!ExchangeInfo || (symbol && !ExchangeInfo[symbol])) {
        ExchangeInfo = {};
        const { data } = await axiosInstance.get(`${accountApiUrl}/fapi/v1/exchangeInfo`);
        data.symbols.map((s) => {
            ExchangeInfo[s.symbol] = _.keyBy(s.filters, 'filterType');
        })
    }
    return symbol ? ExchangeInfo[symbol] : ExchangeInfo;
}

/**
 * 生成 API 签名
 * @param {Object} params - 请求参数
 * @returns {string} 签名
 */
function sign(params) {
    const query = new URLSearchParams(params).toString();
    return crypto.createHmac('sha256', API_SECRET).update(query).digest('hex');
}

/**
 * 获取杠杆账户信息
 * @returns {Array} 杠杆账户信息
 */
let loadMarginAccountTimer = null;
async function loadMarginAccount() {
    if (loadMarginAccountTimer) {
        clearTimeout(loadMarginAccountTimer);
    }
    try {
        const params = {
            timestamp: Date.now(),
        };
        params.signature = sign(params);
        let res = await axiosInstance.get(`https://api.binance.com/sapi/v1/margin/account`, {
            params,
            headers: { 'X-MBX-APIKEY': API_KEY },
        });
        arginAccount = res.data.userAssets.find(item => item.asset === 'USDT').free;
        console.log('loadMarginAccount', arginAccount);
        res = await axiosInstance.get(`https://api.binance.com/sapi/v1/margin/isolated/account`, {
            params,
            headers: { 'X-MBX-APIKEY': API_KEY },
        });
        isolatedAccount = _.get(res.data.assets.find(item => item.quoteAsset.asset === 'USDT'), 'quoteAsset.free', 0);
        console.log('loadisolatedAccount', isolatedAccount);
    } catch (err) {
        console.log('loadMarginAccount', err);
    }
    // 10分钟加载一次
    loadMarginAccountTimer = setTimeout(() => loadMarginAccount(), 10 * 60 * 1000);
}

/**
 * 创建监听密钥
 * @returns {string} 监听密钥
 */
async function createListenKey() {
    const res = await axiosInstance.post(`${accountApiUrl}/fapi/v1/listenKey`, null, {
        headers: { 'X-MBX-APIKEY': API_KEY },
    });
    return res.data.listenKey;
}

/**
 * 续期监听密钥
 * @param {string} listenKey - 监听密钥
 */
async function renewListenKey(listenKey) {
    await axiosInstance.put(`${accountApiUrl}/fapi/v1/listenKey`, null, {
        headers: { 'X-MBX-APIKEY': API_KEY },
    });
}

// 持仓信息缓存
let POSITIONS = [];

/**
 * 加载当前持仓信息
 * @returns {Array} 持仓信息数组
 */
async function funLoadPositions() {
    const params = {
        timestamp: Date.now(),
    };
    params.signature = sign(params);
    const res = await axiosInstance.get(`${accountApiUrl}/fapi/v2/positionRisk`, {
        params,
        headers: { 'X-MBX-APIKEY': API_KEY },
    });

    // 返回所有持仓信息数组，positionAmt 不为 0 的才是有持仓
    POSITIONS = res.data
        .filter(pos => parseFloat(pos.positionAmt) !== 0).map(pos => ({
            symbol: pos.symbol,
            quantity: parseFloat(pos.positionAmt),
            entryPrice: parseFloat(pos.entryPrice),
            leverage: parseInt(pos.leverage),
            unrealizedProfit: parseFloat(pos.unRealizedProfit),
            marginType: pos.marginType,
            side: parseFloat(pos.positionAmt) > 0 ? 'LONG' : 'SHORT',
        }));
    return POSITIONS;
}
// 全局锁，防止并发建仓导致重复下单
let lock = false;

/**
 * 开多仓函数
 * @param {string} symbol - 交易对
 * @param {number} quantity - 下单数量
 * @param {number} takeProfitPct - 止盈百分比
 * @param {number} stopLossPct - 止损百分比
 * @returns {boolean} 是否建仓成功
 */
async function openLong(symbol, quantity, takeProfitPct, stopLossPct) {
    const positionSide = 'LONG';
    // 检查锁，防止重复建仓
    if (lock) {
        console.log(`[锁定中] 忽略重复建仓请求 ${symbol}`);
        return false;
    }

    // 检查当前是否已持有该币种仓位
    const positions = await funLoadPositions();
    if (positions.some(p => p.symbol === symbol)) {
        console.log(`[已持仓] ${symbol}`);
        return false;
    }
    if (positions.length > MAX_POSITIONS) {
        console.log(`[持仓过多] 忽略重复建仓请求 ${symbol}`);
        return false;
    }
    lock = true; // 加锁，防止并发
    // 获取交易对精度信息，调整下单数量
    const exchange = await funGetExchangeInfo(symbol);
    const stepSize = exchange['MARKET_LOT_SIZE']?.stepSize || exchange['LOT_SIZE']?.stepSize;
    if (stepSize) {
        quantity = utils.adjustToStep(quantity, stepSize);
    }
    try {
        // 构造市价单参数
        const orderParams = {
            symbol,
            side: 'BUY',
            type: 'MARKET',
            quantity,
            positionSide,
            timestamp: Date.now(),
        };
        orderParams.signature = sign(orderParams);
        // 发送市价单请求
        const res = await axiosInstance.post(`${accountApiUrl}/fapi/v1/order`, null, {
            params: orderParams,
            headers: { 'X-MBX-APIKEY': API_KEY },
        });
        console.log('[建仓成功]', res.data);
        let position = null;
        // 再次获取持仓，确认建仓成功
        await utils.retry(async () => {
            const updatedPositions = await funLoadPositions();
            position = updatedPositions.find(p => p.symbol === symbol);
            if (!position) throw new Error(`未找到新建持仓: ${symbol}`);
        }, 5, 1000)
        // 计算止盈止损价格，受限于交易所价格限制
        const entry = parseFloat(position.entryPrice);
        const sideFilter = exchange['PERCENT_PRICE_BY_SIDE'] || {};
        const percentFilter = exchange['PERCENT_PRICE'] || {};
        let takeProfit = entry * (1 + takeProfitPct / 100);
        // 市价单止盈止损价格 （上浮0.2%）
        let takeMarketProfit = entry * (1 + (takeProfitPct + 0.2) / 100);

        let stopLoss = entry * (1 - stopLossPct / 100);
        let stopLoss1 = entry * (1 - (stopLossPct + 0.12) / 100);
        let stopLoss2 = entry * (1 - (stopLossPct + 1.5) / 100);

        // 市价单11个点止损价格 （下浮%）
        let stopMarketLoss = entry * (1 - (11) / 100);
        // 修正止盈止损的价格限制
        const askMultiplierUp = parseFloat(sideFilter.askMultiplierUp || percentFilter.multiplierUp || 0);
        if (askMultiplierUp > 0) {
            takeProfit = _.min([takeProfit, entry * (1 + askMultiplierUp)]);
        }
        const bidMultiplierDown = parseFloat(sideFilter.bidMultiplierDown || percentFilter.multiplierDown || 0);
        if (bidMultiplierDown > 0) {
            stopLoss = _.max([stopLoss, entry * (1 - bidMultiplierDown)]);
        }
        // 修正止盈止损的价格精度
        const tickSize = exchange['PRICE_FILTER']?.tickSize || 0;
        if (tickSize > 0) {
            stopLoss = utils.adjustToStep(stopLoss, tickSize);
            stopLoss1 = utils.adjustToStep(stopLoss1, tickSize);
            stopLoss2 = utils.adjustToStep(stopLoss2, tickSize);
            stopMarketLoss = utils.adjustToStep(stopMarketLoss, tickSize);
            takeProfit = utils.adjustToStep(takeProfit, tickSize);
            takeMarketProfit = utils.adjustToStep(takeMarketProfit, tickSize);
        }

        await utils.retry(async () => await placeExitOrder(symbol, 'SELL', 'STOP', quantity, stopLoss, tickSize, positionSide));
        await utils.retry(async () => await placeExitOrder(symbol, 'SELL', 'STOP', quantity, stopLoss1, tickSize, positionSide));
        await utils.retry(async () => await placeExitMarketOrder(symbol, 'SELL', 'STOP_MARKET', stopMarketLoss, positionSide));

        // // 限价止盈单
        // try {
        //     // 下限价止盈单
        //     await placeExitOrder(symbol, 'SELL', 'TAKE_PROFIT', quantity, takeProfit, tickSize, positionSide);
        // } catch (err) {
        //     console.log('限价单失败：', err.response?.data || err)
        // }
        // 市价止盈单
        await utils.retry(async () =>await placeExitMarketOrder(symbol, 'SELL', 'TAKE_PROFIT_MARKET', takeProfit, positionSide));
        lock = false; // 解锁
        return true;
    } catch (err) {
        lock = false; // 出错也要解锁
        // 针对常见错误做详细提示
        if (err?.response?.data?.msg?.includes('Unable to fill')) {
            console.error(`[下单失败] 市场流动性不足: ${symbol}`);
        } else if (err?.response?.data?.msg?.includes('PERCENT_PRICE')) {
            console.error(`[下单失败] 超出价格限制: ${symbol} ${err.response.data.msg}`);
        } else {
            console.error(`[下单失败] ${symbol} ${err}`, err);
        }
        try {
            // 直接平仓
            await utils.retry(async () => await closePosition(symbol, 'SELL', quantity, positionSide));
        } catch (err) {
            console.error(`[平仓失败] ${symbol} ${err}`);
        }
        return true;
    }
}

/**
 * 开空仓函数
 * @param {string} symbol - 交易对
 * @param {number} quantity - 下单数量
 * @param {number} takeProfitPct - 止盈百分比
 * @param {number} stopLossPct - 止损百分比
 * @returns {boolean} 是否建仓成功
 */
async function openShort(symbol, quantity, takeProfitPct, stopLossPct) {
    const positionSide = 'SHORT';
    // 检查锁，防止重复建仓
    if (lock) {
        console.log(`[锁定中] 忽略重复建仓请求 ${symbol}`);
        return false;
    }

    // 检查当前是否已持有该币种仓位
    const positions = await funLoadPositions();
    if (positions.some(p => p.symbol === symbol)) {
        console.log(`[已持仓] ${symbol}`);
        return false;
    }
    if (positions.length > MAX_POSITIONS) {
        console.log(`[持仓过多] 忽略重复建仓请求 ${symbol}`);
        return false;
    }
    lock = true; // 加锁，防止并发

    // 获取交易对精度信息，调整下单数量
    const exchange = await funGetExchangeInfo(symbol);
    const stepSize = exchange['MARKET_LOT_SIZE']?.stepSize || exchange['LOT_SIZE']?.stepSize;
    if (stepSize) {
        quantity = utils.adjustToStep(quantity, stepSize);
    }
    try {
        // 构造市价单参数
        const orderParams = {
            symbol,
            side: 'SELL',
            type: 'MARKET',
            quantity,
            positionSide,
            timestamp: Date.now(),
        };
        orderParams.signature = sign(orderParams);
        // 发送市价单请求
        const res = await axiosInstance.post(`${accountApiUrl}/fapi/v1/order`, null, {
            params: orderParams,
            headers: { 'X-MBX-APIKEY': API_KEY },
        });
        console.log('[建仓成功]', res.data);
        let position = null;
        // 再次获取持仓，确认建仓成功
        await utils.retry(async () => {
            const updatedPositions = await funLoadPositions();
            position = updatedPositions.find(p => p.symbol === symbol);
            if (!position) throw new Error(`未找到新建持仓: ${symbol}`);
        }, 5, 1000)
        // 计算止盈止损价格，受限于交易所价格限制
        const entry = parseFloat(position.entryPrice);
        const sideFilter = exchange['PERCENT_PRICE_BY_SIDE'] || {};
        const percentFilter = exchange['PERCENT_PRICE'] || {};
        let takeProfit = entry * (1 - takeProfitPct / 100);
        // 市价单止盈止损价格 （上浮0.2%）
        let takeMarketProfit = entry * (1 - (takeProfitPct + 0.2) / 100);
        let stopLoss = entry * (1 + stopLossPct / 100);
        let stopLoss1 = entry * (1 + (stopLossPct + 0.12) / 100);
        let stopLoss2 = entry * (1 + (stopLossPct + 1.5) / 100);
        // 市价单11个点止损价格 （下浮%）
        let stopMarketLoss = entry * (1 + ( 11) / 100);
        // 修正止盈止损的价格限制
        const askMultiplierUp = parseFloat(sideFilter.askMultiplierUp || percentFilter.multiplierUp || 0);
        if (askMultiplierUp > 0) {
            takeProfit = _.min([takeProfit, entry * (1 + askMultiplierUp)]);
        }
        const bidMultiplierDown = parseFloat(sideFilter.bidMultiplierDown || percentFilter.multiplierDown || 0);
        if (bidMultiplierDown > 0) {
            stopLoss = _.max([stopLoss, entry * (1 - bidMultiplierDown)]);
        }
        // 修正止盈止损的价格精度
        const tickSize = exchange['PRICE_FILTER']?.tickSize || 0;
        if (tickSize > 0) {
            takeProfit = utils.adjustToStep(takeProfit, tickSize);
            stopLoss = utils.adjustToStep(stopLoss, tickSize);
            stopLoss1 = utils.adjustToStep(stopLoss1, tickSize);
            stopLoss2 = utils.adjustToStep(stopLoss2, tickSize);
            takeMarketProfit = utils.adjustToStep(takeMarketProfit, tickSize);
            stopMarketLoss = utils.adjustToStep(stopMarketLoss, tickSize);
        }
        // 下限价止损单
        // await utils.retry(async () => await placeExitOrder(symbol, 'BUY', 'STOP', quantity, stopLoss, tickSize, positionSide));
        // await utils.retry(async () => await placeExitOrder(symbol, 'BUY', 'STOP', quantity, stopLoss1, tickSize, positionSide));
        // await utils.retry(async () => await placeExitOrder(symbol, 'BUY', 'STOP', quantity, stopLoss2, tickSize, positionSide));

        // 下市价止损单
        // await utils.retry(async () => await placeExitMarketOrder(symbol, 'BUY', 'STOP_MARKET', stopMarketLoss, positionSide));

        // 限价止盈单
        // try {
        //     // 下限价止盈单
        //     await placeExitOrder(symbol, 'BUY', 'TAKE_PROFIT', quantity, takeProfit, tickSize, positionSide);
        // } catch (err) {
        //     console.log('限价单失败：', err.response?.data || err)
        // }
        // 市价止盈单
        await utils.retry(async () =>await placeExitMarketOrder(symbol, 'BUY', 'TAKE_PROFIT_MARKET', takeProfit, positionSide));
        lock = false; // 解锁
        return true;
    } catch (err) {
        lock = false; // 出错也要解锁
        // 针对常见错误做详细提示
        if (err?.response?.data?.msg?.includes('Unable to fill')) {
            console.error(`[下单失败] 市场流动性不足: ${symbol}`);
        } else if (err?.response?.data?.msg?.includes('PERCENT_PRICE')) {
            console.error(`[下单失败] 超出价格限制: ${symbol} ${err.response.data.msg}`);
        } else {
            console.error(`[下单失败] ${symbol} ${err}`);
        }
        try {
            // 直接平仓
            await utils.retry(async () => await closePosition(symbol, 'BUY', quantity, positionSide));
        } catch (err) {
            console.error(`[平仓失败] ${symbol} ${err}`);
        }
        return true;
    }
}

/**
 * 下止盈 / 止损单
 * @param {string} symbol - 交易对
 * @param {string} side - 买卖方向
 * @param {string} type - 订单类型
 * @param {number} quantity - 数量
 * @param {number} stopPrice - 触发价格
 * @param {number} tickSize - 价格步进
 */
async function placeExitOrder(symbol, side, type, quantity, stopPrice, tickSize, positionSide = 'LONG') {
    const isStopLoss = type === 'STOP_MARKET' || type === 'STOP';
    const isLimitType = type === 'STOP' || type === 'TAKE_PROFIT';
    const params = {
        symbol,
        side,
        type,
        stopPrice: Array.isArray(stopPrice) ? stopPrice[0] : stopPrice,
        quantity,
        positionSide,
        workingType: isStopLoss ? 'MARK_PRICE' : 'CONTRACT_PRICE',
        timestamp: Date.now(),
    };

    // 限价单
    if (isLimitType) {
        // 优化：offsetTicks 可配置，默认10
        const offsetTicks = positionSide === 'LONG' ? 1 : -1;
        // 获取限价金额
        params.price = Array.isArray(stopPrice) ? stopPrice[1] : params.stopPrice;
        // 如果限价金额与止损价一致，则需要计算新的止损价
        if (params.price === params.stopPrice) {
            let _newStopPrice = params.price;
            // 根据类型计算新的触发价格
            if (type === 'STOP') {
                // 止损单，触发价格应高于止损价
                _newStopPrice = params.price + offsetTicks * tickSize;
                //  跟止损价一致,防止提前平仓
                // _newStopPrice = params.price;
            } else {
                // 止盈单，触发价格应低于止盈价
                _newStopPrice = params.price - offsetTicks * tickSize;
                // _newStopPrice = params.price;
            }
            // 保证价格精度
            params.stopPrice = utils.adjustToStep(_newStopPrice, tickSize);
        }
    }

    params.signature = sign(params);
    const res = await axiosInstance.post(`${accountApiUrl}/fapi/v1/order`, null, {
        params,
        headers: { 'X-MBX-APIKEY': API_KEY },
    });
    console.log(`[${type}] 下单成功:`, res.data);
}


/**
 * 下止盈 / 止损单
 * @param {string} type - 订单类型
 * @param {number} stopPrice - 止损价格
 */
async function placeExitMarketOrder(symbol, side, type, stopPrice, positionSide = 'LONG') {
    const isStopLoss = type === 'STOP_MARKET' || type === 'STOP';
    const params = {
        symbol: symbol,
        side,
        type,
        stopPrice: stopPrice,
        closePosition: true,
        positionSide,
        workingType: 'MARK_PRICE',
        timestamp: Date.now(),
        ...(isStopLoss && { priceProtect: true })  // 仅止损单时加上
    };
    params.signature = sign(params);
    const res = await axiosInstance.post(`${accountApiUrl}/fapi/v1/order`, null, {
        params,
        headers: { 'X-MBX-APIKEY': API_KEY },
    });
    console.log(`${type} 下单成功:`, res.data);
}

/**
 * 市价平仓函数
 * @param {string} symbol - 交易对，如 'BTCUSDT'
 * @param {string} side - 'SELL' 平多仓，'BUY' 平空仓
 * @param {number} quantity - 要平掉的合约数量
 * @param {string} positionSide - 'LONG' or 'SHORT'
 */
async function closePosition(symbol, side, quantity, positionSide) {
    const params = {
        symbol,
        side,
        type: 'MARKET',
        quantity,
        positionSide,
        timestamp: Date.now()
    };
    params.signature = sign(params);
    try {
        const res = await axios.post(`${accountApiUrl}/fapi/v1/order`, null, {
        params,
        headers: { 'X-MBX-APIKEY': API_KEY }
        });
        console.log(`[市价平仓成功]`, res.data);
    } catch (err) {
        console.error(`[市价平仓失败]`, err?.response?.data || err.message);
    }
}

async function cancelAllOrders(symbol) {
    const params = {
        symbol: symbol,
        timestamp: Date.now(),
    };
    console.log(params);
    params.signature = sign(params);
    const res = await axiosInstance.delete(`${accountApiUrl}/fapi/v1/allOpenOrders`, {
        params,
        headers: { 'X-MBX-APIKEY': API_KEY },
    });
    console.log(`已取消 ${symbol} 所有挂单`, res.data);
}


// 创建订单参数的辅助函数
function createOrderParams(symbol, side, quantity, positionSide) {
    const params = {
        symbol,
        side,
        type: 'MARKET',
        quantity,
        positionSide,
        timestamp: Date.now(),
    };
    params.signature = sign(params);
    return params;
}

// 执行单个订单的辅助函数
async function executeOrder(orderParams, description) {
    try {
        const response = await axiosInstance.post(`${accountApiUrl}/fapi/v1/order`, null, {
            params: orderParams,
            headers: { 'X-MBX-APIKEY': API_KEY },
        });
        return response.data;
    } catch (error) {
        console.error(`[${description}下单失败]`, error?.response?.data?.msg || error.message);
        throw error;
    }
}

// 清理异常仓位的辅助函数
async function cleanupPositions(symbol, quantity) {
    const cleanupTasks = [
        { side: 'BUY', positionSide: 'SHORT', description: 'SHORT' },
        { side: 'SELL', positionSide: 'LONG', description: 'LONG' }
    ];

    await Promise.allSettled(cleanupTasks.map(async ({ side, positionSide, description }) => {
        try {
            await utils.retry(async () => await closePosition(symbol, side, quantity, positionSide), 3, 1000);
            console.log(`[清理成功] ${description}仓位已平仓 ${symbol}`);
        } catch (err) {
            console.error(`[清理失败] ${description}仓位平仓失败 ${symbol}:`, err.message);
        }
    }));
}

async function duichong(symbol, quantity, takeProfitPct) {
    if (lock) {
        console.log(`[锁定中] 忽略重复建仓请求 ${symbol}`);
        return false;
    }

    const positions = await funLoadPositions();
    if (positions.some(p => p.symbol === symbol)) {
        console.log(`[已持仓] ${symbol}`);
        return false;
    }

    lock = true;

    try {
        // 获取交易对精度信息并调整数量
        const exchange = await funGetExchangeInfo(symbol);
        const stepSize = exchange['MARKET_LOT_SIZE']?.stepSize || exchange['LOT_SIZE']?.stepSize;
        if (stepSize) {
            quantity = utils.adjustToStep(quantity, stepSize);
        }

        // 并行执行开多开空订单
        const [sellResult, buyResult] = await Promise.all([
            executeOrder(createOrderParams(symbol, 'SELL', quantity, 'SHORT'), '开空'),
            executeOrder(createOrderParams(symbol, 'BUY', quantity, 'LONG'), '开多')
        ]);

        console.log(`[建仓成功] ${symbol} 多空对冲订单已执行`);

        // 确认建仓并获取入场价格
        let position = null;
        await utils.retry(async () => {
            const updatedPositions = await funLoadPositions();
            position = updatedPositions.find(p => p.symbol === symbol);
            if (!position) throw new Error(`未找到新建持仓: ${symbol}`);
        }, 5, 1000);

        // 计算并设置止盈止损价格
        const entry = parseFloat(position.entryPrice);
        let topPrice = entry * (1 + takeProfitPct / 100);
        let lowPrice = entry * (1 - takeProfitPct / 100);

        const tickSize = exchange['PRICE_FILTER']?.tickSize;
        if (tickSize && tickSize > 0) {
            topPrice = utils.adjustToStep(topPrice, tickSize);
            lowPrice = utils.adjustToStep(lowPrice, tickSize);
        }
        // 设置止盈止损订单
        await Promise.all([
            utils.retry(async () => await placeExitOrder(symbol, 'BUY', 'STOP', quantity, topPrice, tickSize, 'SHORT'), 3, 1000),
            utils.retry(async () => await placeExitOrder(symbol, 'SELL', 'STOP', quantity, lowPrice, tickSize, 'LONG'), 3, 1000)
        ]);

        console.log(`[对冲完成] ${symbol} 入场价:${entry} 平空止损:${topPrice} 平多止损:${lowPrice}`);
        return true;

    } catch (error) {
        console.error(`[对冲失败] ${symbol}:`, error?.response?.data?.msg || error.message);

        // 异常情况下清理可能的部分仓位
        await cleanupPositions(symbol, quantity);
        return true;
    } finally {
        lock = false;
    }
}


/**
 * 主函数：初始化交易环境
 * @param {Function} callback - 回调函数
 */
export default async (callback, onTrade) => {
    API_KEY = config.API_KEY;
    API_SECRET = config.API_SECRET;
    console.log(config);
    if (config.isTest) {
        accountSocketUrl = 'wss://fstream.binancefuture.com';
        accountApiUrl = 'https://testnet.binancefuture.com';
        webSocketUrl = 'wss://fstream.binancefuture.com';
    } else {
        // 真实环境加载
        await loadMarginAccount();
    }

    // 初始化交易所信息
    await funGetExchangeInfo();

    // 加载当前持仓
    const p = await funLoadPositions();
    console.log(p);

    // WebSocket 连接 URL
    const url = `${webSocketUrl}/swift/stream`;

    // 创建账户 WebSocket 连接
    const listenKey = await createListenKey();
    var accountSocket = new WebSocket(`${accountSocketUrl}/ws/${listenKey}`, { agent });

    // 账户 WebSocket 事件处理
    accountSocket.on('open', () => {
        console.log('accountSocketUrl open');
    });
    accountSocket.on('message', async (data) => {
        const msg = JSON.parse(data);
        if (msg.e === 'ACCOUNT_UPDATE') {
            console.log(JSON.stringify(msg));
            let needReLoadPositions = [];

            // 检查是否有平仓操作
            _.forEach(msg.a.P, (item) => {
                if (parseFloat(item.pa) === 0) {
                    needReLoadPositions.push(item.s);
                }
            });
            // 如果有平仓操作，刷新持仓信息
            if (needReLoadPositions.length > 0) {
                // 延时 5 s 刷新
                setTimeout(async () => {
                    const positions = await funLoadPositions();
                    // 取消残单
                    for (const symbol of needReLoadPositions) {
                        // 如果还有持仓，则不取消挂单
                        if (positions.some(p => p.symbol === symbol)) {
                            console.log(`[还剩持仓] ${symbol}，不取消挂单`);
                            continue;
                        }
                        try {
                            await utils.retry(async () => await cancelAllOrders(symbol));
                        } catch (error) {
                            console.error(`取消 ${symbol} 挂单失败:`, error?.response?.data || error);
                        }
                    }
                }, 5000);
            }
        } else if (msg.e === 'ORDER_TRADE_UPDATE') {
            const symbol = msg.o.s;
            const rp = msg.o.rp;
            const orderId = msg.o.i;
            // 成交盈亏不为0
            if (rp != 0) {
                onTrade && onTrade({
                    symbol,
                    orderId,
                    rp,
                    msg,
                    funGetPositions: () => POSITIONS,
                    funSetPositions: (positions) => {
                        POSITIONS = positions;
                    },
                    closePosition,
                });
                rp != 0 && addTrade(symbol, orderId, parseFloat(rp));
            }
        }
    });

    // WebSocket 心跳处理
    accountSocket.on('ping', (data) => accountSocket.pong(data));

    // WebSocket 关闭处理
    accountSocket.on('close', function () {
        console.log(new Date().toISOString(), 'AccountSocket closed');
        process.exit(0);
    });

    // 定时续期 listenKey（每 30 分钟）
    setInterval(() => {
        renewListenKey(listenKey)
            .then(() => console.log('🔄 listenKey 已续期'))
            .catch(console.error);
    }, 30 * 60 * 1000);


    // 创建一个串行队列，确保同一时间只处理一个建仓任务，避免并发下单
    var openLongQueue = queue(function (task, callback) {
        openLong(...task.args).then(callback).catch((error) => {
            console.error(error);
            callback(true);
        });
    }, 1);
    var openShortQueue = queue(function (task, callback) {
        openShort(...task.args).then(callback).catch((error) => {
            console.error(error);
            callback(true);
        });
    }, 1);
    var duichongQueue = queue(function (task, callback) {
        duichong(...task.args).then(callback).catch((error) => {
            console.error(error);
            callback(true);
        });
    }, 1);

    var funCreateSocket = () => {
        // 创建市场数据 WebSocket 连接
        var socket = new WebSocket(url, { agent });

        // 市场数据 WebSocket 心跳处理
        socket.on('ping', (data) => socket.pong(data));

        // 市场数据 WebSocket 关闭处理
        socket.on('close', function () {
            console.log(new Date().toISOString(), 'WebSocket closed');
            process.exit(0);
        });
        return socket;
    }

    // 执行回调函数，传递必要的函数和数据
    callback({
        funGetExchangeInfo,
        funGetSymbols,
        createSocket: funCreateSocket,
        funcGetSymbolDailPrice,
        utils,
        config,
        getTrades: () => trades,
        addTrade,
        getBalance: () => arginAccount ? arginAccount * 100 : config.balance,
        getSide: () => isolatedAccount >=1 ? 'long' : 'short',
        funGetPositions: () => POSITIONS,
        openLong: (...args) => new Promise(resolve => openLongQueue.push({args}, resolve)),
        openShort: (...args) => new Promise(resolve => openShortQueue.push({args}, resolve)),
        duichong: (...args) => new Promise(resolve => duichongQueue.push({args}, resolve)),
        getMarkPrice: async (symbol) => {
            const res = await axios.get(`${accountApiUrl}/fapi/v1/premiumIndex`, {
                params: { symbol },
            });
            return parseFloat(res.data.markPrice);
        },
    })
};

// 全局异常处理
process.on('uncaughtException', (error) => {
    console.error(new Date().toISOString(), 'Uncaught Exception:', error);
    process.exit(0);
});
